home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Imaging Engine / Interface.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  23.5 KB  |  810 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        Interface.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains interface routines for the PostScript Imaging Engine.
  6.  
  7.      Version:    Technology:    Quickdraw GX 1.1.x
  8.       
  9.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  10. */
  11.  
  12. #include <MacMemory.h>
  13. #include <Resources.h>
  14. #include <GXGraphics.h>
  15. #include "GXToPSBuildConfig.h"
  16. #include "GXToPostScript.h"
  17. #include "IOUtilities.h"
  18. #include "RDUtil.h"
  19. #include "FontHandler.h"
  20. #include "PublicPostScriptIE.h"
  21. #include "private.h"
  22. #include "PSIEResources.h"
  23. #include "GXErrors.h"
  24.  
  25. #ifdef resumeLabel
  26.     #undef resumeLabel
  27. #endif
  28. #define resumeLabel(exception)
  29.  
  30. /************************************
  31.  
  32.     Function PSIENewInk:
  33.     Called to create an ink for our base graphics
  34.     state.  We do this because we want a zero
  35.     length profile to avoid the initial creation
  36.     of the state to download a calibrated RGB space
  37.     for PostScript.
  38.     
  39. *************************************/
  40. gxInk PSIENewInk();
  41. gxInk PSIENewInk()
  42.     {
  43.         gxInk                        newInk;
  44.         gxColorProfile    aProfile;
  45.         gxColor                    aColor;
  46.         
  47.         aProfile = GXNewColorProfile(0, nil);
  48.         newInk = GXNewInk();
  49.         GXGetInkColor(newInk, &aColor);
  50.         aColor.profile = aProfile;
  51.         GXSetInkColor(newInk, &aColor);
  52.         GXDisposeColorProfile(aProfile);    
  53.     
  54.         return(newInk);
  55.         
  56.     }//PSIENewInk
  57.  
  58.  
  59.  
  60.  
  61. /************************************
  62.  
  63.     Routine: CreateGrayColorSet
  64.  
  65.     Routine to create a 256 entry colorset for
  66.     a gray ramp. 0 is black,
  67.     255 is white.
  68.     
  69.     
  70. *************************************/
  71. gxColorSet CreateGrayColorSet(void)
  72.     {
  73.         gxColorSet                theSet;
  74.         gxSetColor                theGrays[256];
  75.         gxSetColor*                pColor = theGrays;
  76.         short                            i;
  77.                 
  78.         
  79.         for (i = 0; i < 256; ++i) {
  80.                     
  81.             pColor->gray = (gxColorValue)(i << 8) | i;        // duplicate the value in both bytes of the short.
  82.             ++pColor;
  83.         
  84.         }//end for
  85.  
  86.         theSet = GXNewColorSet(gxGraySpace, 256, theGrays);
  87.     
  88.         return(theSet);
  89.     
  90.     }//CreateGrayColorSet
  91.  
  92. //<FF>
  93. /*******************************
  94.     Routine EnterPostScriptIE:
  95.     
  96.     Routine initializes the PostScript Imaging Engine for the processing
  97.     of a series of shapes. (Usually coming from the Transfer Mode Resolver/
  98.     Picture Walker
  99.     
  100.     context:            (returned) A context for the client of the imaging engine.
  101.     params:                The client's parameter block to initialize the IE with.
  102.     deviceMapping    view device mapping for printer.
  103.     fhContext:        A valid font handler context.
  104.     compatFlags:    compatability flags.
  105.     
  106. ********************************/
  107. // Note, change: DL 7/13/97: Changed imagedata handle to pointer to struct
  108. OSErr EnterPostScriptIE(TPSIEContext *context, CGXtoPostScriptDevice *psDevice, gxPostScriptImageDataRec *params,
  109.                                                         TFontHandlerContext fhContext, TCompatibilityFlags* compatFlags)
  110.     {
  111.         OSErr                            status;
  112.         TIEGlobalsPtr            pGlobals;
  113.         
  114.         status = PrNewHandleClear((Handle*)context, (sizeof(TIEGlobalsRec)        // Room for structure plus
  115.                                                     + sizeof(TGstate) +                                                            // room for base graphics state
  116.                                                     params->gsaveLimit *                                                         // plus one graphics state and one workspace
  117.                                                     (sizeof(TGstate) + sizeof(Handle))) );                    // for each gsave level
  118.         nrequire(status, failed_AllocGlobals);
  119.         
  120.         HLock((Handle)*context);
  121.         
  122.         pGlobals = *(TIEGlobalsHdl)(*context);            //    Dereference the handle.
  123.         
  124.         
  125.         /******
  126.             The offset to the array of workspace handles
  127.             is the size of the globals record + (gsaveLimit + 1) * sizeof(TGstate)
  128.             because the handles come after the array of graphics states
  129.             and there are gsaveLimit graphics states plus one for the base state
  130.         ******/
  131.  
  132.         pGlobals->offsetToWorkspace = 
  133.                     sizeof(TIEGlobalsRec) + (params->gsaveLimit + 1) * sizeof(TGstate);
  134.         
  135.         /*******
  136.             Set up grapics state pointers
  137.             base graphics state is gStateArray[0]
  138.             gStateNest[0] is gStateArray[1],
  139.             Thus gStateNest[-1] is the base graphics state.
  140.             This is done so that the gStateNest array
  141.             is in phase (as opposed to one off) with
  142.             the array of transforms that will come into
  143.             PostScriptDrawShape.
  144.         *******/
  145.         pGlobals->baseGstate = &(pGlobals->gStateArray[0]);
  146.         pGlobals->gStateNest = &(pGlobals->gStateArray[1]);
  147.  
  148.  
  149.         /** Initialize the ResDump utility **/
  150.  
  151.         pGlobals->psDevice = psDevice;
  152.         
  153.         nrequire(status = RDInit(pGlobals->psDevice, &pGlobals->rdMap), failed_RDInit);        //    Allocate a Res Dump Util map.
  154.  
  155.         /** Set up the substitutions for PostScript strings **/
  156.         
  157.         status = RDSetSubstitutions(pGlobals->rdMap, 6,
  158.                                     '(', "\p\\(",                /* ( becomes \( for string quoting */
  159.                                     ')', "\p\\)",                /* ( becomes \( for string quoting */
  160.                                     '\\', "\p\\\\",            /* \ becomes \\ becuase \ is the quote character */
  161.                                     13, "\p\\r",                /* carriage return becomes \r becuase PS scanner will substitute a raw carriage return for a line feed */
  162.                                     10, "\p\\n",                 /* line feed becomes \n becuase who knows what PS scanner might do */
  163.                                      4, "\p\\004" );        /* ctrl-D becomes octal-4 becuase ctrl-d is eof in serial connected PS */
  164.         
  165.         nrequire(status, failed_SetSubs);    
  166.         
  167.         //    copy in the initialization parameters.            
  168.         BlockMoveData(params, &(pGlobals->params), sizeof(gxPostScriptImageDataRec));
  169.         
  170.         // Make sure we are an ownder of the profile in the imagedata
  171.         if (pGlobals->params.devCProfile != nil)
  172.             GXCloneColorProfile(pGlobals->params.devCProfile);
  173.         
  174.         // Compatability flags.
  175.         pGlobals->compatFlags = *compatFlags;
  176.         
  177.         /******
  178.             Validate the rendering options
  179.         ******/
  180.         
  181.         //Set language level to 1 if portable postscript is set
  182.         if (pGlobals->params.renderOptions & gxPortablePostScriptOption)
  183.             pGlobals->params.languageLevel = 1;
  184.         
  185.         //Level2 color on < level2 printer or portable PostScript makes no sense
  186.         if ( (pGlobals->params.languageLevel < 2) || (pGlobals->params.renderOptions & gxPortablePostScriptOption))
  187.             pGlobals->params.renderOptions &= ~gxUseLevel2ColorOption;
  188.         
  189.  
  190.  
  191.         /** Set up the rest of the globals **/
  192.         
  193.         pGlobals->fhContext = fhContext;
  194.                                                                      
  195.         pGlobals->workSpaceIndex = 0;                                            // Workspace zero is available.
  196.                 
  197.         /** If necessary, create a gray ramp color set for 8-bit PS image operator **/
  198.         
  199.         if (pGlobals->params.devCSpace == gxGraySpace)
  200.             pGlobals->graySet = CreateGrayColorSet();
  201.         else
  202.             pGlobals->graySet = nil;
  203.             
  204.         nrequire(status = GXGetGraphicsError(nil), failed_CreateGrays);
  205.         
  206.         /** 
  207.             For Level-2 Color, make a copy of the default profile - this is because we can't clone and dispose of the default
  208.                 Also allocate the collection for the CRD database
  209.         **/
  210.         
  211.         if (pGlobals->params.renderOptions & gxUseLevel2ColorOption) {
  212.     
  213.             pGlobals->defaultProfileCopy = GXCopyToColorProfile(nil, GXGetDefaultColorProfile());
  214.             nrequire(status = GXGetGraphicsError(nil), failed_CreateProfile);
  215.     
  216.         }    else {
  217.  
  218.             pGlobals->defaultProfileCopy = nil;
  219.  
  220.         }//end if
  221.             
  222.         
  223.  
  224.         /* Ignore these notices, because Imaging Engine is almost guarenteed to cause them */
  225.         
  226.         GXIgnoreGraphicsNotice(mapping_unaffected);
  227.         GXIgnoreGraphicsNotice(graphic_type_cannot_be_mapped);
  228.         GXIgnoreGraphicsNotice(request_exceeds_available_data);
  229.  
  230.         GXIgnoreGraphicsNotice(glyph_tangents_have_no_effect);
  231.         GXIgnoreGraphicsWarning(index_out_of_range);
  232.         GXIgnoreGraphicsWarning(count_out_of_range);
  233.  
  234.         #ifdef IEdoVALIDATION
  235.             GXSetValidation(gxPublicValidation + 
  236.                                             gxAllObjectValidation +
  237.                                             gxApHeapValidation);
  238.         #endif
  239.         
  240.         #ifdef usePerfLib
  241.             status = InitPerf(&(pGlobals->perfGlobals), 4, 16, true, true, "\ppost", 0, "\p", false, 0, 0, 0);
  242.             if (status)
  243.                 PerfControl(pGlobals->perfGlobals, true);
  244.             else
  245.                 dprintf(notrace, "Init Performance failed");
  246.         #endif
  247.  
  248.  
  249.         /* successful allocation and initialization, return */
  250.         return(status);
  251.         
  252. failed_CreateProfile:
  253. failed_CreateGrays:
  254. failed_WorkSpace:
  255.  
  256. failed_SetSubs:
  257.         RDShutdown(pGlobals->rdMap);
  258.  
  259. failed_RDInit:
  260.         DisposeHandle((Handle)context);
  261.  
  262. failed_AllocGlobals:
  263.  
  264.         return(status);    
  265.     
  266.     }//EnterPostScriptIE
  267.  
  268.  
  269. //<FF>
  270. /*************************************
  271.     Routine: PostScriptInitGraphics
  272.     Routine sets up a known initial graphics state.
  273.     This should be called at the start of each logical page (or EPS file)
  274.  
  275.     context:                    Imaging engine context.
  276.     hParams:                    Imaging Engine parameters.
  277.     devMapping:                view device mapping for page.
  278.     halftoneRecord:        halftone record for page.
  279.     
  280. **************************************/
  281. OSErr    PostScriptInitGraphics(TPSIEContext context, gxPostScriptImageDataRec *imageData, gxMapping *devMapping, gxFormatHalftoneInfo *halftoneRecord)
  282.     {
  283.         OSErr                            status;
  284.         TGstate                        *pGstate;
  285.         TIEGlobalsPtr            pGlobals;
  286.         TRDParams                    rdParams;                                // Pointer to this will be passed down call chain.
  287.         unsigned char            stateFlags;
  288.         gxShape                        defaultShape;
  289.         gxColorProfile        oldProfile;
  290.         
  291.         /** Time data throughput **/
  292.         #ifdef TIMEIO
  293.         {
  294.             Handle        h;
  295.             long            i;
  296.             long            *p;
  297.             long            time;
  298.             long            size = 500000;
  299.             
  300.             status = PrNewHandle(&h, size);
  301.             ncheck(status);
  302.             HLockHi(h);            
  303.             p = (long*)*h;
  304.             for (i = 0; i < (size / 4); ++i)
  305.                 *p++ = 0x2525250D;
  306.  
  307.             time = TickCount();
  308.             status = Send_GXBufferData(*h, size, gxNoBufferOptions);
  309.             ncheck(status);
  310.             status = Send_GXWriteData("\n", 1);
  311.             ncheck(status);
  312.             time = (TickCount() - time) / 60;
  313.             
  314.             #if DEBUGLEVEL >= DEBUGFEEDBACK
  315.                 dprintf(notrace, "bytes per second: %d", size / time);
  316.             #endif
  317.  
  318.             (void)PrDisposeHandle(h);
  319.             
  320.         }
  321.         #endif
  322.                 
  323.         /** Lock the context, All the pritnf's can move mem **/
  324.         stateFlags = HGetState((Handle)context);
  325.         HLock((Handle)context);
  326.         
  327.         pGlobals = *(TIEGlobalsHdl)(context);            //    Dereference the context handle.
  328.         
  329.         pGlobals->deviceMapping = *devMapping;
  330.  
  331.         /*******
  332.             Copy the new image data handle into the globals and deal with the profile ownership
  333.             Warning:  Changing languageLevel or some renderoptions or flipping the PortablePostScript
  334.             bit after EnterPostScriptIE can cause PostScript errors.  Some proc-sets may not
  335.             have been downloaded.  It really only makes sense to change color space and profile
  336.             here.
  337.         ******/
  338.  
  339.         oldProfile = pGlobals->params.devCProfile;                    // Get the old profile
  340.         
  341.         BlockMoveData(imageData, &(pGlobals->params), sizeof(gxPostScriptImageDataRec));
  342.  
  343.         if (pGlobals->params.devCProfile != nil)                        // Make sure we own the new one.
  344.             GXCloneColorProfile(pGlobals->params.devCProfile);
  345.             
  346.         if (oldProfile != nil)                                                            // Dispose of the old one.
  347.             GXDisposeColorProfile(oldProfile);
  348.     
  349.                 
  350.         /** Get ready to image the next page **/
  351.         
  352.         pGlobals->ieStateFlags = eInitializeGstate;        // all other bits clear
  353.         pGlobals->gStateDepth = -1;                                        //    Index will Point to base graphics state.
  354.         pGlobals->pRDParams = &rdParams;                            //  Point to this one for this call chain.
  355.         pGlobals->theFont = nil;                                            // No font yet.
  356.         pGlobals->fontSize = 0;                                                //     thus no font size.
  357.         pGlobals->fontTangent.x = 0;                                    //    and no tangent. (A real one couldn't be 0-0)
  358.         pGlobals->fontTangent.y = 0;
  359.         pGlobals->textStyle = nil;                                        //    No text face.
  360.         pGlobals->theColorSet = nil;                                    // no bitmap color set yet.
  361.  
  362.         /* set up top of nested graphics state */
  363.         
  364.         defaultShape = GXNewShape(gxRectangleType);            // We'll use the characteristics of the default rectangle.
  365.         
  366.         /** Output the initial graphics state **/
  367.         
  368.         rdParams.rdMap = pGlobals->rdMap;
  369.         rdParams.resType = 'STR#';
  370.         rdParams.resID = kScriptResID;
  371.         rdParams.rdFlags = eRDnoOptions;
  372.         
  373.         /*****
  374.             Put md on stack (this way, evil applications use of currentdict to check for 
  375.                 laserPrep definitions fails since md is empty
  376.                 Apps that bother to check for laserprep operators this way won't find them and thus do the 'clean'
  377.                 thing.  Apps that don't check continue to work the way they always did
  378.         *****/
  379.         rdParams.resIndex = kMDBegin;
  380.         nrequire(status = RDResPrintf(&rdParams), failed_MDBegin);
  381.         
  382.         /** Put Imaging Engine ProcSet dictionary on top of dict stack **/
  383.         
  384.         nrequire(status = BeginProcSetDict(&rdParams), failed_Dict);
  385.         
  386.         #if DEBUGLEVEL>1        
  387.             if (pGlobals->params.renderOptions & gxNeedsCommentsOption) {
  388.                 
  389.                 rdParams.resIndex = kInitComment;
  390.                 nrequire(status = RDResPrintf(&rdParams, "Begin", 5), failed_ResPrintf);
  391.                 
  392.             }//end if
  393.         #endif                
  394.  
  395.         /** Set up the initial style for the page **/
  396.         
  397.         pGlobals->theStyle = GXCloneStyle(GXGetShapeStyle(defaultShape));
  398.  
  399.         /** nrequire(status = StyleDrone((TIEGlobalsHdl)(context), pGlobals->theStyle), failed_State); **/
  400.         /**   ^^^ Commented out, now handled when first shape is draw **/
  401.         
  402.         /** Set up the initial halftone screens for the page **/
  403.  
  404.         if (halftoneRecord != nil) {
  405.         
  406.             status = HalftonePrimitive((TIEGlobalsHdl)(context), halftoneRecord);
  407.             nrequire(status, failed_halftone);
  408.         
  409.         }//end if
  410.         
  411.         /** Now make sure we define the default halftone in our ProcSet dictionary **/
  412.         rdParams.resIndex = kDefineDefaultScreen;
  413.         nrequire(status = RDResPrintf(&rdParams), failed_ResPrintf);
  414.         
  415.         
  416.         /*****
  417.             For Portable RGB PostScript, make the colorspace a Calibrated RGB space
  418.             based on the device profile
  419.         ****/
  420.         if (    (pGlobals->params.devCSpace == gxRGBSpace) && 
  421.                     (pGlobals->params.renderOptions & gxPortablePostScriptOption)) {
  422.  
  423.             status = CalibratedRGBSpacePrimitive((TIEGlobalsHdl)context, pGlobals->params.devCProfile);
  424.             nrequire(status, failed_space);
  425.             
  426.             rdParams.resIndex = kSetPortableColorSpace;
  427.             nrequire(status = RDResPrintf(&rdParams), failed_ResPrintf);    
  428.         
  429.         }//end if
  430.         
  431.                         
  432.         /*** Create up the base graphics state ***/
  433.         pGstate = pGlobals->baseGstate;
  434.         pGstate->pointsAvail = pGlobals->params.pathLimit;    //    assumed we start at initial value passed.
  435.         pGstate->theInk = PSIENewInk();
  436.         pGstate->halftoneTag = nil;
  437.         pGstate->theTransform = GXNewTransform();
  438.         pGstate->flags = eNoGstateFlags;
  439.         
  440.         /** Stuff for Level-2 color if necessary , harmless to set it in either case **/
  441.         pGstate->currSpace = gxNoSpace;
  442.         pGstate->level2DevSpace = false;
  443.         if (pGlobals->defaultProfileCopy != nil)
  444.             pGstate->currProfile = GXCloneColorProfile(pGlobals->defaultProfileCopy);
  445.             
  446.         /** Make sure the color in the printer graphics state reflects our base state **/
  447.         status = InkDrone((TIEGlobalsHdl)(context), pGstate->theInk);
  448.         nrequire(status, failed_Ink);
  449.         
  450.         /** Grab the "port" mapping in the current graphics state **/
  451.         rdParams.resIndex = kSavePortMapping;
  452.         nrequire(status = RDResPrintf(&rdParams), failed_ResPrintf);
  453.         
  454.         #ifdef noBaseState
  455.             /*****
  456.                 If we are ignoring transform lists for old apps, initialize our base graphics state
  457.                     by calling the gsave.  Bumps graphicsState level up to 0.  We still need a base
  458.                     state.  Pass true for internalOnly to inhibit the output of a gsave operator
  459.             *****/
  460.             if (pGlobals->compatFlags.flags1 & kPSIgnoreTransformList) {
  461.                 status = DoGsave((TIEGlobalsHdl)(context), true);
  462.                 nrequire(status, failed_gsave);
  463.             }//end if
  464.         #endif
  465.  
  466.         pGlobals->ieStateFlags = eInitializeGstate;                    // So first shape initializes printer.
  467.  
  468.     #if DEBUGLEVEL>1        
  469.         if (pGlobals->params.renderOptions & gxNeedsCommentsOption) {
  470.         
  471.             rdParams.resIndex = kInitComment;
  472.             nrequire(status = RDResPrintf(&rdParams, "End", 3), failed_ResPrintf);
  473.             
  474.         }//end if
  475.     #endif
  476.  
  477.     #ifdef TIMEIE
  478.         pGlobals->pageTime = TickCount();
  479.         pGlobals->shapeTime = 0;
  480.         pGlobals->shapeCount = 0;
  481.         #if DEBUGLEVEL >= DEBUGFEEDBACK
  482.             dprintf(trace, "Starting to image page");
  483.         #endif
  484.     #endif
  485.  
  486. failed_gsave:
  487. failed_Ink:
  488. failed_space:
  489. failed_halftone:
  490. failed_State:
  491. failed_ResPrintf:
  492. failed_Dict:
  493. failed_MDBegin:
  494.         GXDisposeShape(defaultShape);
  495.                 
  496.         HSetState((Handle)context, stateFlags);
  497.         return(status);    
  498.     
  499.     }//PostScriptInitGraphics
  500.  
  501.  
  502.  
  503. //<FF>
  504. /*************************************
  505.     Routine: PostScriptRestoreGraphics
  506.     Routine restores graphics state to the known state
  507.     created by PostScriptInitGraphics.
  508.     Does all grestores, etc…  Disposes of all transforms
  509.     in Imaging Engine internal state.
  510.     
  511.     This should be called at the end of each logical page (or EPS file)
  512.     
  513. **************************************/
  514. OSErr    PostScriptRestoreGraphics(TPSIEContext context)
  515.     {
  516.         OSErr                        status = noErr;
  517.         short                        i;
  518.         TIEGlobalsPtr        pGlobals;
  519.         TRDParams                rdParams;
  520.         Boolean                    internalOnly = false;                    // normally output grestores as well as clean up.
  521.     
  522.         pGlobals = *(TIEGlobalsHdl)context;
  523.         
  524.         #if    USECOMPATFLAGS
  525.             if (pGlobals->compatFlags.flags1 & kPSIgnoreTransformList)        // If we are ignoring transforms then grestore is internal only.
  526.                 internalOnly = true;
  527.         #endif
  528.                 
  529.         pGlobals->pRDParams = &rdParams;                            //  Point to this one for this call chain.
  530.                 
  531.         rdParams.rdMap = pGlobals->rdMap;
  532.         rdParams.resType = 'STR#';
  533.         rdParams.resID = kScriptResID;
  534.         rdParams.rdFlags = eRDnoOptions;
  535.         
  536.         for (i = pGlobals->gStateDepth; i >= 0; --i) {
  537.             
  538.             status = DoGrestore((TIEGlobalsHdl)context, internalOnly);
  539.             nrequire(status, failed_Grestore);
  540.             
  541.         }//end for
  542.         
  543.         /*** Now dispose of items hanging off of base graphics state (keep in sync with code in DoGrestore) ***/
  544.  
  545.         pGlobals = *(TIEGlobalsHdl)context;
  546.         DisposeGstateItems(pGlobals->baseGstate);
  547.         
  548.         pGlobals = *(TIEGlobalsHdl)context;
  549.         GXDisposeStyle(pGlobals->theStyle);                            // We cloned ourselves a copy of shape's style.
  550.         
  551.         if (pGlobals->theColorSet != nil)
  552.             GXDisposeColorSet(pGlobals->theColorSet);
  553.         
  554.         if (pGlobals->textStyle != nil)
  555.             GXDisposeStyle(pGlobals->textStyle);
  556.  
  557.  
  558.         /* Clean up any non-document level color rendering dictionaries downloaded for this job if necessary */
  559.         
  560.         if ( pGlobals->params.renderOptions & gxPageIndependentPostScript) {
  561.         
  562.             status = RemoveDownloadedCRDs((TIEGlobalsHdl)context);
  563.             nrequire(status, failed_removeCRDs);
  564.             
  565.         }//end if
  566.         
  567.         /** remove ProcSet dictionary from top of dict stack **/
  568.         
  569.         nrequire(status = EndProcSetDict(&rdParams), failed_Dict);
  570.         
  571.         /** Remove MD from dictionary stack **/
  572.         
  573.         rdParams.resIndex = kMDEnd;
  574.         nrequire(status = RDResPrintf(&rdParams), failed_MDEnd);
  575.         
  576.     #ifdef TIMEIE
  577.         pGlobals->pageTime = TickCount() - pGlobals->pageTime;
  578.  
  579.         #if DEBUGLEVEL >= DEBUGFEEDBACK
  580.                 dprintf(trace, "Page Time: %d sec., #shapes: %d, shape Time: %d sec.", pGlobals->pageTime / 60, 
  581.                               pGlobals->shapeCount, pGlobals->shapeTime / 1000);
  582.         #endif
  583.     #endif
  584.  
  585. failed_removeCRDs:
  586. failed_MDEnd:
  587. failed_Dict:
  588. failed_Grestore:
  589.  
  590.         return(status);
  591.     
  592.     }//PostScriptRestoreGraphics
  593.  
  594. #if GXTOPOSTSCRIPTLIBRARY
  595. /**********************************************
  596.     Routine to download the Procsets:
  597.     
  598.     The code is different from the original imaging engine in that 
  599.     the PostScript code resources are explicitly downloaded here.
  600.     In the original imaging engine, the IE returned a resource containing
  601.     a list of resources which the GX printing system would then download.
  602.  
  603. ***********************************************/
  604. OSErr    PostScriptIEDownloadProcSets(TPSIEContext context)
  605.     {
  606.         short    basicProcArray[]    =    {
  607.                     kProcCopyRightNoticeID,
  608.                     kStartProcID,
  609.                     kStartProcIDL1+1,
  610.                     kStartProcIDL1+2,
  611.                     kStartProcIDL1+3,
  612.                     kStartProcIDL1+4,
  613.                     kStartProcIDL1+5,
  614.                     kStartProcIDL1+6,
  615.                     kStartProcIDL1+7,
  616.                     kStartProcIDL1+8,
  617.                     kLastProcID
  618.                 };
  619.  
  620.         short portableProcArray[] =        {
  621.                     kProcCopyRightNoticeID,
  622.                     kStartProcID,
  623.                     kLevel2ColorProcID,                // Portable color requires some of the same stuff as level-2 for response functions.
  624.                     kPortableColorProcID,
  625.                     kStartProcIDL1+1,
  626.                     kStartProcIDL1+2,
  627.                     kStartProcIDL1+3,
  628.                     kStartProcIDL1+4,
  629.                     kStartProcIDL1+5,
  630.                     kStartProcIDL1+6,
  631.                     kStartProcIDL1+7,
  632.                     kStartProcIDL1+8,
  633.                     kLastProcID
  634.                 };
  635.         
  636.         short    level2ColorProcArray[] = {
  637.                     kProcCopyRightNoticeID,
  638.                     kStartProcID,                 
  639.                     kLevel2ColorProcID,        
  640.                     kStartProcIDL1+1,        
  641.                     kStartProcIDL1+2,        
  642.                     kStartProcIDL1+3,        
  643.                     kStartProcIDL1+4,        
  644.                     kStartProcIDL1+5,        
  645.                     kStartProcIDL1+6,        
  646.                     kStartProcIDL1+7,        
  647.                     kStartProcIDL1+8,        
  648.                     kLastProcID                    
  649.                 };
  650.  
  651.         TIEGlobalsPtr pGlobals = *(TIEGlobalsHdl)context;
  652.         long                    resourceCount;
  653.         OSErr                    status;
  654.         short                    *resourceArray;
  655.  
  656.         CGXtoPostScriptDevice        *theDevice = pGlobals->psDevice;
  657.         
  658.         if (pGlobals->params.renderOptions & gxPortablePostScriptOption) {
  659.             resourceArray = portableProcArray;
  660.             resourceCount = sizeof(portableProcArray) / sizeof(short);
  661.         } else {
  662.             if (pGlobals->params.renderOptions & gxUseLevel2ColorOption) {
  663.                 resourceArray = level2ColorProcArray;
  664.                 resourceCount = sizeof(level2ColorProcArray) / sizeof(short);
  665.             } else {
  666.                 resourceArray = basicProcArray;
  667.                 resourceCount = sizeof(basicProcArray) / sizeof(short);
  668.             }//end if
  669.         }//end if
  670.         
  671.         /** Now stream out the proc-sets **/
  672.         
  673.         for (int i = 0; i < resourceCount; ++i) {
  674.         
  675.             short        ID = resourceArray[i];
  676.             Handle    hProc;
  677.             status = FetchResource('wstr', ID, &hProc);
  678.             nrequire(status, failed_fetchResource);
  679.             
  680.             HLock(hProc);
  681.             short        size = *(short*)(*hProc);
  682.             char*        data = (*hProc) + sizeof(short);            // skip past size word in wstr resource.
  683.             status = theDevice->BufferData(data, size, gxNoBufferOptions);
  684.             ReleaseResource(hProc);
  685.             nrequire(status, failed_download);
  686.             
  687.         }//end for
  688.  
  689. failed_download:
  690. failed_fetchResource:
  691.     
  692.         return(status);
  693.             
  694.     }
  695. #else
  696. //<FF>
  697. /**********************************************
  698.     Routine PostScriptIEGetProcSetList
  699.     Returns the range of id's and type of the resources for the
  700.     PostScript Procedure set, based upon the parameters specified at init time.
  701.  
  702.     context:        A valid imaging engine context.
  703.  
  704. ************************************************/
  705. OSErr    _PostScriptIEGetProcSetList(TPSIEContext context, gxProcSetListPtr procSetList)
  706.     {
  707.         TIEGlobalsPtr pGlobals = *(TIEGlobalsHdl)context;
  708.  
  709.  
  710.         procSetList->controlType = kControlResType;
  711.         procSetList->dataType = kBinaryResType;        
  712.  
  713.         if (pGlobals->params.renderOptions & gxPortablePostScriptOption) {
  714.         
  715.             procSetList->controlid = kControlResIDPortable;
  716.  
  717.             #if DEBUGLEVEL >= DEBUGFEEDBACK
  718.                 dprintf(trace, "Using portable proc-set");
  719.             #endif
  720.             
  721.         } else {
  722.         
  723.             if (pGlobals->params.renderOptions & gxUseLevel2ColorOption)
  724.                 procSetList->controlid = kControlResIDL2Color;
  725.             else
  726.                 procSetList->controlid = kControlResID;
  727.             
  728.         }//end if
  729.         
  730.         return(noErr);
  731.     }//PostScriptIEGetProcSetList
  732. #endif
  733.  
  734.  
  735. //<FF>
  736. /***********************
  737.     Routine: PostScriptIEReplaceFontHandler
  738.     
  739.     This function is used to replace the font handler context for the imaging engine.
  740.     This can be called when doing single pass printing when we don't have all the pages
  741.     before imaging.
  742. ************************/
  743. void        PostScriptIEReplaceFontHandler(TPSIEContext context, TFontHandlerContext newFHContext)
  744.     {
  745.         TIEGlobalsPtr pGlobals = *(TIEGlobalsHdl)context;
  746.         pGlobals->fhContext = newFHContext;    
  747.     }
  748.  
  749.  
  750. //<FF>
  751.  
  752. /*******************************
  753.     Routine ExitPostScriptIE:
  754.     
  755.     Routine shuts down the PostScript Imaging Engine
  756.     
  757.     context:        (returned) A context for the client of the imaging engine.
  758.     
  759. ********************************/
  760. OSErr    ExitPostScriptIE(TPSIEContext context)
  761.     {
  762.         OSErr                        status = noErr;
  763.         Handle                    *workSpaceArray;                    // Pointer to first handle in array o'workspaces
  764.         
  765.         TIEGlobalsPtr pGlobals = *(TIEGlobalsHdl)context;
  766.         short                    i;
  767.         
  768.         HLock((Handle)context);
  769.         
  770.         #ifdef usePerfLib
  771.             status = PerfDump(pGlobals->perfGlobals, "\pDevilGerbil:Imaging Utilities:Performance.output", true, 80);
  772.             nrequire(status, failed_Performance);
  773.             
  774.             TermPerf(pGlobals->perfGlobals);
  775.         #endif
  776.                                                     
  777.         workSpaceArray = (Handle*)((long)pGlobals + pGlobals->offsetToWorkspace); 
  778.  
  779.         /** Dispose of all workspaces **/
  780.         for (i = 0; i < pGlobals->params.gsaveLimit; i++) {
  781.         
  782.             if (*workSpaceArray != nil)
  783.                 DisposeHandle(*workSpaceArray);
  784.                 
  785.             ++workSpaceArray;
  786.         
  787.         }//end for
  788.  
  789.  
  790.         if (pGlobals->params.devCProfile != nil)
  791.             GXDisposeColorProfile(pGlobals->params.devCProfile);
  792.  
  793.         if (pGlobals->graySet != nil)
  794.             GXDisposeColorSet(pGlobals->graySet);
  795.         
  796.         if (pGlobals->defaultProfileCopy != nil)
  797.             GXDisposeColorProfile(pGlobals->defaultProfileCopy);
  798.                                             
  799.         RDShutdown(pGlobals->rdMap);
  800.  
  801.         DisposeHandle((Handle)context);    
  802.  
  803.         
  804. failed_Performance:
  805.         return(status);
  806.  
  807.     }//ExitPostScriptIE
  808.  
  809.  
  810.